package com.yc.springmvc.web;

import com.google.gson.Gson;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

public class MyDispatchServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        // 替换 /springmvc_demo_war_exploded 为空
        requestURI = requestURI.replace(req.getContextPath(),"");

        // 根据URI => 定位控制器 => 省略...
        IndexController controller = new IndexController();

        // 判断响应当前请求  => 不包含继承的方法
        final Method[] methods = controller.getClass().getDeclaredMethods();
        // 控制器方法
        Method handlerMethod = null;
        for (Method method : methods) {
            final RequestMapping requestMapping =
                    method.getAnnotation(RequestMapping.class);

            if (requestMapping != null) {
                String path = requestMapping.value()[0];
                if(path.startsWith("/") == false){
                    path = "/" + path;
                }
                if( path.equals(requestURI)){
                    handlerMethod = method;
                    break;
                }
            }
        }

        if (handlerMethod == null) {
            // 如果有 DefaultServlet =>
            // 如果没有 => 静态资源映射
            // 如果还没有 => 404
            return;
        }
        // 方法的参数集合
        final Parameter[] parameters = handlerMethod.getParameters();
        // 方法参数值集合
        List<Object> paramValus = new ArrayList<>();
        for (Parameter parameter : parameters) {
            //  提取请求中对应的参数值
            final String value = req.getParameter(parameter.getName());
            // 转型
            if (parameter.getType().isAssignableFrom(String.class)) {
                paramValus.add(value);
            } else if (parameter.getType().isAssignableFrom(int.class) ||
                    parameter.getType().isAssignableFrom(Integer.class)) {
                paramValus.add(Integer.parseInt(value));
            } else {
                // 实体对象
                // 扩展:
            }
        }
        try {
            Object result = handlerMethod.invoke(controller, paramValus.toArray());
            if(controller.getClass().getAnnotation(RestController.class)!=null){
                // @RestController => json ModelAndView
                if (result instanceof ModelAndView){
                    // 跳转页面
                } else {
                    Gson gson = new Gson();
                    final String json = gson.toJson(result);
                    resp.setContentType("application/json;charset=utf-8");
                    resp.getWriter().append(json);
                }
            } else if(controller.getClass().getAnnotation(Controller.class)!=null){
                if(handlerMethod.getAnnotation(ResponseBody.class)!=null){
                    // 转 json
                } else {
                    // 根据 controller 的注解
                    // @Contoller => 响应重定向
                    String address = (String) result;
                    address = address.substring("redirect:".length());
                    resp.sendRedirect(address);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("执行控制方法失败!",e);
        }
    }
}
